package com.atguigu.dga.governance.assess.security;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.atguigu.dga.governance.assess.Assessor;
import com.atguigu.dga.governance.bean.AssessParam;
import com.atguigu.dga.governance.bean.GovernanceAssessDetail;
import com.atguigu.dga.meta.bean.TableMetaInfo;
import org.apache.commons.lang3.StringUtils;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileStatus;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.math.BigDecimal;
import java.net.URI;
import java.net.URISyntaxException;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.List;




@Component("FILE_ACCESS_PERMISSION")
public class FileAccessPermissionAssessor extends Assessor {


    //   1  提取相关元数据  参数 。。
    //   2  准备递归遍历
    //      递归工具    FileSystem
    //      递归起点    一级子目录
    //      递归结果的容器  收集所有超过权限的文件/目录 位置
    //      递归任务处理工具   permission
    //   3  递归执行
    //      循环启点目录
    //        如果遇到是 中间节点（目录)
    //               采集  处理 （权限检查)     展开下一层次 递归回调自己    ==>收入结果容器
    //               叶子节点(文件)
    //               采集 处理 （权限检查)                               ==>收入结果容器
    //   4  根据结果容器 进行 评价
    //        如果容器有内容  差评
    @Override
    public void checkProblem(GovernanceAssessDetail governanceAssessDetail, AssessParam assessParam) throws Exception {
        //   1  提取相关元数据  参数 。。
        TableMetaInfo tableMetaInfo = assessParam.getTableMetaInfo();
        String metricParamsJson = assessParam.getGovernanceMetric().getMetricParamsJson();
        JSONObject paramJsonObj = JSON.parseObject(metricParamsJson);
        String filePermission = paramJsonObj.getString("file_permission");
        String dirPermission = paramJsonObj.getString("dir_permission");


        //    递归遍历
        List<String> beyondPermissionFileList=   checkPermission(tableMetaInfo,filePermission,dirPermission);

        //   4  根据结果容器 进行 评价
        //        如果容器有内容  差评
        if(beyondPermissionFileList.size()>0){
            governanceAssessDetail.setAssessScore(BigDecimal.ZERO);
            governanceAssessDetail.setAssessProblem("超过权限文件、目录："+ StringUtils.join(beyondPermissionFileList,"," ));
        }


    }

    private List<String> checkPermission(TableMetaInfo tableMetaInfo, String filePermission, String dirPermission) throws  Exception  {
        //   2  准备递归遍历
        //      递归工具    FileSystem
        //      递归起点    一级子目录
        //      递归结果的容器  收集所有超过权限的文件/目录 位置
        //      递归任务处理工具   permission

        FileSystem fileSystem = FileSystem.get(new URI(tableMetaInfo.getTableFsPath()), new Configuration(), tableMetaInfo.getTableFsOwner());
        FileStatus[] fileStatuses = fileSystem.listStatus(new Path(tableMetaInfo.getTableFsPath()));
        List<String> beyondPermissionFileList =new ArrayList<>();
        //  3 递归执行
        checkPermissionRec(fileSystem,fileStatuses,beyondPermissionFileList,filePermission,dirPermission);
        //  4 使用完工具收回
        fileSystem.close();
        return beyondPermissionFileList;
    }
    //  3 递归执行
    private void checkPermissionRec(FileSystem fileSystem, FileStatus[] fileStatuses, List<String> beyondPermissionFileList, String filePermission, String dirPermission) throws  Exception {
        // 循环启点目录
        for (FileStatus fileStatus : fileStatuses) {
            if(fileStatus.isDirectory()){
                //        如果遇到是 中间节点（目录)
                //               采集  处理 （权限检查)      ==>收入结果容器
                boolean  isBeyondPermission=   isBeyondPermissionForOne(fileStatus,dirPermission);
                if(isBeyondPermission){
                    beyondPermissionFileList.add(fileStatus.getPath().toString());
                 }
                // 展开下一层次 递归回调自己
                FileStatus[] subFileStatusArr = fileSystem.listStatus(fileStatus.getPath());
                checkPermissionRec(fileSystem,subFileStatusArr,beyondPermissionFileList,filePermission,dirPermission);



            }else{
                //               叶子节点(文件)
                //               采集 处理 （权限检查)                               ==>收入结果容器
                boolean  isBeyondPermission=   isBeyondPermissionForOne(fileStatus,filePermission);
                if(isBeyondPermission) {
                    beyondPermissionFileList.add(fileStatus.getPath().toString());
                }

            }

        }


    }

    //针对一个文件或目录进行权限检查
    private boolean isBeyondPermissionForOne(FileStatus fileStatus, String dirPermission) {
        int userOrdinal = fileStatus.getPermission().getUserAction().ordinal();
        int groupOrdinal = fileStatus.getPermission().getGroupAction().ordinal();
        int otherOrdinal = fileStatus.getPermission().getOtherAction().ordinal();

        Integer userParam = Integer.valueOf(dirPermission.substring(0, 1));
        Integer groupParam = Integer.valueOf(dirPermission.substring(1, 2));
        Integer otherParam = Integer.valueOf(dirPermission.substring(2));
        if(userOrdinal>userParam
        ||groupOrdinal>groupParam
                ||otherOrdinal>otherParam){
            return true;
        }

        return false;
    }
}
